﻿//========================================================= 
/**@file FileVirtualCipher.h
 * @brief 以文件形式虚拟的密钥器
 * 
 * @date 2017-10-13   14:54:53
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_FILEVIRTUALCIPHER_H_
#define _LIBZHOUYB_FILEVIRTUALCIPHER_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"
#include "../../wrapper/jsoncpp/jsoncpp_extractor.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace pinpad {
//--------------------------------------------------------- 
/**
 * @brief 以Json文件形式虚拟的密钥器
 * @date 2017-10-13 14:55
 */
class FileVirtualCipher : public RefObject
{
protected:
    /// 存储密钥
    Json::Value _keyMap;
    /// 密钥文件路径
    string _path;
    /// 获取指定索引的主密钥Json对象
    bool _MK(uint mkIndex, Json::Value*& pMK)
    {
        string key = ArgConvert::ToString(mkIndex);
        if(!_keyMap.isMember(key))
            return false;
        pMK = &(_keyMap[key]);
        return true;
    }
    /// 获取指定索引的工作密钥Json对象
    bool _WK(uint mkIndex, Json::Value*& pWK)
    {
        Json::Value* pMK = NULL;
        if(!_MK(mkIndex, pMK))
            return false;
        pWK = &((*pMK)["WK"]);
        return true;
    }
public:
    FileVirtualCipher()
    {
        _path = "";
    }
    /// 返回密钥的Json字符串
    size_t ToJSON(ByteBuilder& sJson)
    {
        Json::FastWriter writer;
        string jsonMsg = writer.write(_keyMap);
        sJson.Append(ByteArray(jsonMsg.c_str(), jsonMsg.length()));
        return jsonMsg.length();
    }
    /// 打开指定的密钥文件
    bool Load(const char* path)
    {
        ifstream fin;
        _path = _strput(path);
        fin.open(_path.c_str(), ios::in);
        if(fin.fail())
            return false;

        Json::Reader reader(Json::Features::strictMode());
        if(!reader.parse(fin, _keyMap, false))
        {
            fin.close();
            return false;
        }
        return true;
    }
    /// 保存到原始文件中
    bool Save()
    {
        return Save(_path.c_str());
    }
    /// 保存到新的文件中
    bool Save(const char* path)
    {
        string doc = _strput(path);
        ofstream fout;
        fout.open(doc.c_str(), ios::out);
        if(fout.fail())
            return false;

        Json::StyledWriter writer;
        string jsonMsg = writer.write(_keyMap);

        fout.write(jsonMsg.c_str(), jsonMsg.length());
        fout.close();
        return true;
    }
    /// 下载指定索引的主密钥
    bool DownloadMK(uint mkIndex, const ByteArray& mk)
    {
        string sMk = ArgConvert::ToString(mkIndex);
        Json::Value& jsonMK = _keyMap[sMk];
        
        ByteBuilder kVal(16);
        ByteConvert::ToAscii(mk, kVal);
        jsonMK["MK"] = kVal.GetString();
        return true;
    }
    /// 下载指定索引的工作密钥
    bool DownloadWK(uint mkIndex, uint wkIndex, const ByteArray& wk)
    {
        Json::Value* pWK = NULL;
        if(!_WK(mkIndex, pWK))
            return false;
        string sWk = ArgConvert::ToString(wkIndex);
        ByteBuilder kVal(16);
        ByteConvert::ToAscii(wk, kVal);
        (*pWK)[sWk] = kVal.GetString();
        return true;
    }
    /// 删除指定索引的主密钥
    bool RemoveMK(uint mkIndex)
    {
        string k = ArgConvert::ToString(mkIndex);
        _keyMap.removeMember(k);
        return true;
    }
    /// 删除指定索引的工作密钥
    bool RemoveWK(uint mkIndex, uint wkIndex)
    {
        Json::Value* pMK = NULL;
        if(_MK(mkIndex, pMK))
            return false;
        string k = ArgConvert::ToString(wkIndex);
        (*pMK).removeMember(k);
        return true;
    }
    /// 获取指定索引的主密钥值
    bool GetMK(uint mkIndex, ByteBuilder& mk)
    {
        Json::Value* pMK = NULL;
        if(!_MK(mkIndex, pMK))
            return false;
        const char KEY_MK[] = "MK";
        if(!(*pMK).isMember(KEY_MK))
            return false;
        string sKey = (*pMK)[KEY_MK].asString();
        DevCommand::FromAscii(sKey.c_str(), mk);
        return true;
    }
    /// 获取指定索引的工作密钥值
    bool GetWK(uint mkIndex, uint wkIndex, ByteBuilder& wk)
    {
        Json::Value* pWK = NULL;
        if(!_WK(mkIndex, pWK))
            return false;
        string wkKey = ArgConvert::ToString(wkIndex);
        if(!(*pWK).isMember(wkKey))
            return false;
        string sKey = (*pWK)[wkKey].asString();
        DevCommand::FromAscii(sKey.c_str(), wk);
        return true;
    }
};
//--------------------------------------------------------- 
} // namespace pinpad
} // namespace application 
} // namespace zhou_yb 
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_FILEVIRTUALCIPHER_H_
//========================================================= 